package org.zjx.window.operation;


import org.zjx.window.window.IWindow;

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 * 操作执行器接口
 * 定义窗口操作的标准契约，包括鼠标、键盘、截图和图像识别等功能
 *
 * @author zjx
 * @since 1.0
 */
public interface OperationExecutor {

    // ========== 窗口关联 ==========

    /**
     * 获取关联的窗口实例
     *
     * @return 关联的窗口实例，可能为null
     */
    IWindow getWindow();

    /**
     * 设置关联的窗口实例
     *
     * @param window 要关联的窗口实例
     */
    void setWindow(IWindow window);

    // ========== 截图操作 ==========

    /**
     * 截取整个窗口区域的屏幕图像
     *
     * @return 窗口区域的屏幕截图，不会返回null
     * @throws IllegalStateException 如果窗口不可用或截图失败
     */
    BufferedImage screenshot();

    /**
     * 截取窗口内指定区域的屏幕图像
     *
     * @param region 要截取的区域（相对于窗口坐标）
     * @return 指定区域的屏幕截图，不会返回null
     * @throws IllegalArgumentException 如果region为 null或无效区域
     * @throws IllegalStateException 如果窗口不可用或截图失败
     */
    BufferedImage screenshot(Rectangle region);

    // ========== 鼠标操作 ==========

    /**
     * 移动鼠标到屏幕绝对坐标
     *
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     */
    void move(int x, int y);

    /**
     * 移动鼠标到屏幕绝对坐标（双精度版本）
     *
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     */
    default void move(double x, double y) {
        move((int) x, (int) y);
    }

    /**
     * 移动鼠标到窗口相对坐标
     *
     * @param x 窗口内相对X坐标
     * @param y 窗口内相对Y坐标
     */
    void gameMove(int x, int y);

    /**
     * 移动鼠标到窗口相对坐标（双精度版本）
     *
     * @param x 窗口内相对 X坐标
     * @param y 窗口内相对 Y坐标
     */
    default void gameMove(double x, double y) {
        gameMove((int) x, (int) y);
    }

    /**
     * 在窗口相对区域内随机移动鼠标
     *
     * @param rectangle 窗口内的相对区域
     * @throws IllegalArgumentException 如果rectangle为 null
     */
    void gameMove(Rectangle rectangle);

    /**
     * 在指定屏幕坐标点击鼠标
     *
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     */
    void click(int x, int y);

    /**
     * 在指定屏幕坐标点击鼠标（双精度版本）
     *
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     */
    default void click(double x, double y) {
        click((int) x, (int) y);
    }

    /**
     * 在当前鼠标位置点击指定按钮
     *
     * @param button 鼠标按钮：1-左键, 2-中键, 3-右键
     * @throws IllegalArgumentException 如果button不是1,2,3
     */
    void click(int button);

    /**
     * 按下鼠标按钮
     *
     * @param button 鼠标按钮：1-左键, 2-中键, 3-右键
     * @throws IllegalArgumentException 如果button不是1,2,3
     */
    void pressMouse(int button);

    /**
     * 释放鼠标按钮
     *
     * @param button 鼠标按钮：1-左键, 2-中键, 3-右键
     * @throws IllegalArgumentException 如果button不是1,2,3
     */
    void releaseMouse(int button);

    /**
     * 获取当前鼠标位置
     *
     * @return 当前鼠标的屏幕坐标，不会返回null
     */
    Point getMousePosition();

    /**
     * 拖拽鼠标从起点到终点
     *
     * @param fromX 起点屏幕X坐标
     * @param fromY 起点屏幕Y坐标
     * @param toX 终点屏幕X坐标
     * @param toY 终点屏幕Y坐标
     */
    void drag(int fromX, int fromY, int toX, int toY);

    /**
     * 拖拽鼠标从起点到终点（双精度版本）
     *
     * @param fromX 起点屏幕X坐标
     * @param fromY 起点屏幕Y坐标
     * @param toX 终点屏幕X坐标
     * @param toY 终点屏幕Y坐标
     */
    default void drag(double fromX, double fromY, double toX, double toY) {
        drag((int) fromX, (int) fromY, (int) toX, (int) toY);
    }

    // ========== 键盘操作 ==========

    /**
     * 按下并释放指定键码
     *
     * @param keyCode 键盘键码（如 KeyEvent.VK_A）
     */
    void press(int keyCode);

    /**
     * 按下指定键码（不释放）
     *
     * @param keyCode 键盘键码
     */
    void pressKey(int keyCode);

    /**
     * 释放指定键码
     *
     * @param keyCode 键盘键码
     */
    void releaseKey(int keyCode);

    /**
     * 输入文本（自动转换为按键序列）
     *
     * @param text 要输入的文本
     * @throws IllegalArgumentException 如果text为null
     */
    void input(String text);

    /**
     * 执行快捷键组合（同时按下多个键）
     *
     * @param keyCodes 键盘键码序列
     * @throws IllegalArgumentException 如果keyCodes为null或空数组
     */
    void hotkey(int... keyCodes);


    // ========== 工具方法 ==========

    /**
     * 延迟指定毫秒数
     *
     * @param milliseconds 要延迟的毫秒数
     * @throws IllegalArgumentException 如果milliseconds为负数
     */
    void delay(long milliseconds);

    /**
     * 获取底层的Robot实例
     *
     * @return AWT Robot实例，不会返回null
     */
    Robot getRobot();

    // ========== WindowOperation 支持 ==========

    /**
     * 执行窗口操作
     *
     * @param operation 要执行的操作
     * @throws IllegalArgumentException 如果operation为null
     */
    default void execute(WindowOperation operation) {
        operation.execute(this);
    }

    /**
     * 顺序执行多个窗口操作
     *
     * @param operations 要执行的操作序列
     * @throws IllegalArgumentException 如果operations为null或包含null元素
     */
    default void executeSequence(WindowOperation... operations) {
        for (WindowOperation op : operations) {
            op.execute(this);
        }
    }
}